# include "Inventory.h"

# include "ObjectPickUp.h"

# include "ObjectInventory.h"
# include "Armor.h"
# include "Weapon.h"
# include "Shield.h"
# include "Jewel.h"

Inventory::Inventory()
{

}

Inventory::~Inventory()
{
	for ( std::map<std::string, Armor*>::iterator it = myHeadArmors.begin(); it != myHeadArmors.end(); it++ )
	{
		delete it->second;
	}
	myHeadArmors.clear();

	for ( std::map<std::string, Armor*>::iterator it = myBodyArmors.begin(); it != myBodyArmors.end(); it++ )
	{
		delete it->second;
	}
	myBodyArmors.clear();

	for ( std::map<std::string, Armor*>::iterator it = myArmsArmors.begin(); it != myArmsArmors.end(); it++ )
	{
		delete it->second;
	}
	myArmsArmors.clear();

	for ( std::map<std::string, Armor*>::iterator it = myHipsArmors.begin(); it != myHipsArmors.end(); it++ )
	{
		delete it->second;
	}
	myHipsArmors.clear();

	for ( std::map<std::string, Armor*>::iterator it = myFeetArmors.begin(); it != myFeetArmors.end(); it++ )
	{
		delete it->second;
	}
	myFeetArmors.clear();

	for ( std::map<std::string, Weapon*>::iterator it = mySwords.begin(); it != mySwords.end(); it++ )
	{
		delete it->second;
	}
	mySwords.clear();

	for ( std::map<std::string, Weapon*>::iterator it = myAxes.begin(); it != myAxes.end(); it++ )
	{
		delete it->second;
	}
	myAxes.clear();

	for ( std::map<std::string, Shield*>::iterator it = myShields.begin(); it != myShields.end(); it++ )
	{
		delete it->second;
	}
	myShields.clear();

	for ( std::map<std::string, Jewel*>::iterator it = myNecklaces.begin(); it != myNecklaces.end(); it++ )
	{
		delete it->second;
	}
	myNecklaces.clear();

	for ( std::map<std::string, Jewel*>::iterator it = myRings.begin(); it != myRings.end(); it++ )
	{
		delete it->second;
	}
	myRings.clear();
}

Armor* Inventory::findArmor( const std::string& name)
{
	if ( myHeadArmors.find( name) != myHeadArmors.end() )
	{
		return myHeadArmors.find( name)->second;
	}

	if ( myBodyArmors.find( name) != myBodyArmors.end() )
	{
		return myBodyArmors.find( name)->second;
	}

	if ( myArmsArmors.find( name) != myArmsArmors.end() )
	{
		return myArmsArmors.find( name)->second;
	}

	if ( myHipsArmors.find( name) != myHipsArmors.end() )
	{
		return myHipsArmors.find( name)->second;
	}
	
	if ( myFeetArmors.find( name) != myFeetArmors.end() )
	{
		return myFeetArmors.find( name)->second;
	}

	return NULL;
}

Weapon* Inventory::findWeapon( const std::string& name)
{
	if ( mySwords.find( name) != mySwords.end() )
	{
		return mySwords.find( name)->second;
	}

	if ( myAxes.find( name) != myAxes.end() )
	{
		return myAxes.find( name)->second;
	}

	return NULL;
}

Shield* Inventory::findShield( const std::string& name)
{
	if ( myShields.find( name) != myShields.end() )
	{
		return myShields.find( name)->second;
	}

	return NULL;
}

Jewel* Inventory::findJewel( const std::string& name)
{
	if ( myNecklaces.find( name) != myNecklaces.end() )
	{
		return myNecklaces.find( name)->second;
	} 

	if ( myRings.find( name) != myRings.end() )
	{
		return myRings.find( name)->second;
	}

	return NULL;
}

std::map<std::string, Armor*>& Inventory::getHeadArmors()
{
	return myHeadArmors;
}

std::map<std::string, Armor*>& Inventory::getBodyArmors()
{
	return myBodyArmors;
}

std::map<std::string, Armor*>& Inventory::getArmsArmors()
{
	return myArmsArmors;
}

std::map<std::string, Armor*>& Inventory::getHipsArmors()
{
	return myHipsArmors;
}

std::map<std::string, Armor*>& Inventory::getFeetArmors()
{
	return myFeetArmors;
}


std::map<std::string, Weapon*>& Inventory::getSwords()
{
	return mySwords;
}

std::map<std::string, Weapon*>& Inventory::getAxes()
{
	return myAxes;
}

std::map<std::string, Shield*>& Inventory::getShields()
{
	return myShields;
}

std::map<std::string, Jewel*>& Inventory::getNecklaces()
{
	return myNecklaces;
}

std::map<std::string, Jewel*>& Inventory::getRings()
{
	return myRings;
}

void Inventory::addBaseEquipment()
{
	myBodyArmors.insert( std::pair< Ogre::String, Armor*>( "BodyArmor", new Armor()));

	myBodyArmors["BodyArmor"]->setName( "BodyArmor");
	myBodyArmors["BodyArmor"]->setType( BODY_ARMOR);
	myBodyArmors["BodyArmor"]->setMeshName( "Armor1.mesh");

	myFeetArmors.insert( std::pair< Ogre::String, Armor*>( "FeetArmor", new Armor()));

	myFeetArmors["FeetArmor"]->setName( "FeetArmor");
	myFeetArmors["FeetArmor"]->setType( FEET_ARMOR);
	myFeetArmors["FeetArmor"]->setMeshName( "Shoes1.mesh");

	mySwords.insert( std::pair< Ogre::String, Weapon*>( "Sword1", new Weapon()));

	mySwords["Sword1"]->setName( "Sword1");
	mySwords["Sword1"]->setType( SWORD);
	mySwords["Sword1"]->setMeshName( "Sword1.mesh");
	mySwords["Sword1"]->setHand( ONE);

	myAxes.insert( std::pair< Ogre::String, Weapon*>( "Axe1", new Weapon()));

	myAxes["Axe1"]->setName( "Axe1");
	myAxes["Axe1"]->setType( AXE);
	myAxes["Axe1"]->setMeshName( "Axe1.mesh");
	myAxes["Axe1"]->setHand( TWO);

	myShields.insert( std::pair< Ogre::String, Shield*>( "Shield1", new Shield()));

	myShields["Shield1"]->setName( "Shield1");
	myShields["Shield1"]->setType( SHIELD);
	myShields["Shield1"]->setMeshName( "Shield1.mesh");
}

bool Inventory::isHeadArmorsEmpty()
{
	return myHeadArmors.empty();
}

bool Inventory::isBodyArmorsEmpty()
{
	return myBodyArmors.empty();
}

bool Inventory::isArmsArmorsEmpty()
{
	return myArmsArmors.empty();
}

bool Inventory::isHipsArmorsEmpty()
{
	return myHipsArmors.empty();
}

bool Inventory::isFeetArmorsEmpty()
{
	return myFeetArmors.empty();
}

bool Inventory::isSwordsEmpty()
{
	return mySwords.empty();
}

bool Inventory::isAxesEmpty()
{
	return myAxes.empty();
}

bool Inventory::isShieldsEmpty()
{
	return myShields.empty();
}

bool Inventory::isNecklacesEmpty()
{
	return myNecklaces.empty();
}

bool Inventory::isRingsEmpty()
{
	return myRings.empty();
}

void Inventory::add( ObjectPickUp* object)
{
	lua_State* stateTmp = lua_open();
	luaL_openlibs( stateTmp);
	unsigned int indiceTmp = 1;

	switch ( object->getObjectType() )
	{
		case HEAD_ARMOR:
		case ARMS_ARMOR:
		case BODY_ARMOR:
		case HIPS_ARMOR:
		case FEET_ARMOR:
		{
			Armor* armorTmp = new Armor();
			
			luaL_dofile( stateTmp, LUA_ARMORS);
			lua_settop( stateTmp, 0);

			lua_getglobal( stateTmp, object->getName().c_str());

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			armorTmp->setType( lua_tonumber( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			armorTmp->setName( lua_tostring( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			armorTmp->setMeshName( lua_tostring( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pushnumber ( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			armorTmp->setArmor( lua_tonumber( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pop( stateTmp, 1);

			add( armorTmp);
		}
		break;

		case SWORD:
		case AXE:
		{
			Weapon* weaponTmp = new Weapon();
			
			luaL_dofile( stateTmp, LUA_WEAPONS);
			lua_settop( stateTmp, 0);

			lua_getglobal( stateTmp, object->getName().c_str());

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			weaponTmp->setType( lua_tonumber( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			weaponTmp->setName( lua_tostring( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			weaponTmp->setMeshName( lua_tostring( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			weaponTmp->setHand( lua_tonumber( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			weaponTmp->setDamageMin( lua_tonumber( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			weaponTmp->setDamageMax( lua_tonumber( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pop( stateTmp, 1);

			add( weaponTmp);
		}
		break;

		case SHIELD:
		{
			Shield *shieldTmp = new Shield();

			luaL_dofile( stateTmp, LUA_SHIELDS);
			lua_settop( stateTmp, 0);

			lua_getglobal( stateTmp, object->getName().c_str());

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			shieldTmp->setType( lua_tonumber( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			shieldTmp->setName( lua_tostring( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			shieldTmp->setMeshName( lua_tostring( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			shieldTmp->setArmor( lua_tonumber( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pushnumber( stateTmp, indiceTmp++);
			lua_gettable( stateTmp, -2);
			shieldTmp->setChance( lua_tonumber( stateTmp, -1));
			lua_pop( stateTmp, 1);

			lua_pop( stateTmp, 1);

			add( shieldTmp);
		}
		break;
	}
	
	lua_close( stateTmp);
}

void Inventory::add( ObjectInventory* object)
{
	switch ( object->getType() )
	{
		case SWORD:
		mySwords.insert( std::pair<std::string, Weapon*>( object->getName(), (Weapon*) object));
		break;

		case AXE:
		myAxes.insert( std::pair<std::string, Weapon*>( object->getName(), (Weapon*) object));
		break;

		case HEAD_ARMOR:
		myHeadArmors.insert( std::pair<std::string, Armor*>( object->getName(), (Armor*) object));
		break;

		case ARMS_ARMOR:
		myArmsArmors.insert( std::pair<std::string, Armor*>( object->getName(), (Armor*) object));
		break;

		case BODY_ARMOR:
		myBodyArmors.insert( std::pair<std::string, Armor*>( object->getName(), (Armor*) object));
		break;

		case HIPS_ARMOR:
		myHipsArmors.insert( std::pair<std::string, Armor*>( object->getName(), (Armor*) object));
		break;

		case FEET_ARMOR:
		myFeetArmors.insert( std::pair<std::string, Armor*>( object->getName(), (Armor*) object));
		break;

		case SHIELD:
		myShields.insert( std::pair<std::string, Shield*>( object->getName(), (Shield*) object));
		break;

		case RING:
		myRings.insert( std::pair<std::string, Jewel*>( object->getName(), (Jewel*) object));
		break;

		case NECKLACE:
		myNecklaces.insert( std::pair<std::string, Jewel*>( object->getName(), (Jewel*) object));
		break;
	}
}